(function($){
	$.fn.tipTip = function(options) {
		var defaults = { 
			activation: "hover",
			keepAlive: false,
			maxWidth: "180px",
			edgeOffset: 0,
			defaultPosition: "right",
			delay: 100,
			fadeIn: 100,
			fadeOut: 100,
			attribute: "title",
			content: false, 
		  	enter: function(){},
		  	exit: function(){}
	  	};
	 	var opts = $.extend(defaults, options);
	 	
	 	
	 	if($("#tipHolder").length <= 0){
	 		var tipHolder = $('<div id="tipHolder" style="max-width:'+ opts.maxWidth +';"></div>');
			var tipContent = $('<div id="tipContent"></div>');
			var tipArrow = $('<div id="tipArrow"></div>');
			$("body").append(tipHolder.html(tipContent).prepend(tipArrow.html('<div id="tipArrowInner"></div>')));
		} else {
			var tipHolder = $("#tipHolder");
			var tipContent = $("#tipContent");
			var tipArrow = $("#tipArrow");
		}
		
		return this.each(function(){
			var org_elem = $(this);
			if(opts.content){
				var org_title = opts.content;
			} else {
				var org_title = org_elem.attr(opts.attribute);
			}
			if(org_title != ""){
				if(!opts.content){
					org_elem.removeAttr(opts.attribute);
				}
				var timeout = false;
				
				if(opts.activation == "hover"){
					org_elem.hover(function(){
						active_tiptip();
					}, function(){
						if(!opts.keepAlive){
							deactive_tiptip();
						}
					});
					if(opts.keepAlive){
						tipHolder.hover(function(){}, function(){
							deactive_tiptip();
						});
					}
				} else if(opts.activation == "focus"){
					org_elem.focus(function(){
						active_tiptip();
					}).blur(function(){
						deactive_tiptip();
					});
				} else if(opts.activation == "click"){
					org_elem.click(function(){
						active_tiptip();
						return false;
					}).hover(function(){},function(){
						if(!opts.keepAlive){
							deactive_tiptip();
						}
					});
					if(opts.keepAlive){
						tipHolder.hover(function(){}, function(){
							deactive_tiptip();
						});
					}
				}
			
				function active_tiptip(){
					opts.enter.call(this);
					tipContent.html(org_title);
					tipHolder.hide().removeAttr("class").css("margin","0");
					tipArrow.removeAttr("style");
					
					var top = parseInt(org_elem.offset()['top']);
					var left = parseInt(org_elem.offset()['left']);
					var org_width = parseInt(org_elem.outerWidth());
					var org_height = parseInt(org_elem.outerHeight());
					var tip_w = tipHolder.outerWidth();
					var tip_h = tipHolder.outerHeight();
					var w_compare = Math.round((org_width - tip_w) / 2);
					var h_compare = Math.round((org_height - tip_h) / 2);
					var marg_left = Math.round(left + w_compare);
					var marg_top = Math.round(top + org_height + opts.edgeOffset);
					var t_class = "";
					var arrow_top = "";
					var arrow_left = Math.round(tip_w - 12) / 2;

                    if(opts.defaultPosition == "bottom"){
                    	t_class = "Bottom";
                   	} else if(opts.defaultPosition == "top"){ 
                   		t_class = "Top";
                   	} else if(opts.defaultPosition == "left"){
                   		t_class = "Left";
                   	} else if(opts.defaultPosition == "right"){
                   		t_class = "Right";
                   	}
					
					var right_compare = (w_compare + left) < parseInt($(window).scrollLeft());
					var left_compare = (tip_w + left) > parseInt($(window).width());
					
					if((right_compare && w_compare < 0) || (t_class == "Right" && !left_compare) || (t_class == "Left" && left < (tip_w + opts.edgeOffset + 5))){
						t_class = "Right";
						arrow_top = Math.round(tip_h - 13) / 2;
						arrow_left = -12;
						marg_left = Math.round(left + org_width + opts.edgeOffset);
						marg_top = Math.round(top + h_compare);
					} else if((left_compare && w_compare < 0) || (t_class == "Left" && !right_compare)){
						t_class = "Left";
						arrow_top = Math.round(tip_h - 13) / 2;
						arrow_left =  Math.round(tip_w);
						marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));
						marg_top = Math.round(top + h_compare);
					}

					var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());
					var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;
					
					if(top_compare || (t_class == "Bottom" && top_compare) || (t_class == "Top" && !bottom_compare)){
						if(t_class == "Top" || t_class == "Bottom"){
							t_class = "Top";
						} else {
							t_class = t_class+"Top";
						}
						arrow_top = tip_h;
						marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));
					} else if(bottom_compare | (t_class == "Top" && bottom_compare) || (t_class == "Bottom" && !top_compare)){
						if(t_class == "Top" || t_class == "Bottom"){
							t_class = "Bottom";
						} else {
							t_class = t_class+"Bottom";
						}
						arrow_top = -12;						
						marg_top = Math.round(top + org_height + opts.edgeOffset);
					}
				
					if(t_class == "RightTop" || t_class == "LeftTop"){
						marg_top = marg_top + 5;
					} else if(t_class == "RightBottom" || t_class == "LeftBottom"){		
						marg_top = marg_top - 5;
					}
					if(t_class == "LeftTop" || t_class == "LeftBottom"){	
						marg_left = marg_left + 5;
					}
					tipArrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"});
					tipHolder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","Tip"+t_class);
					
					if (timeout){ clearTimeout(timeout); }
					timeout = setTimeout(function(){ tipHolder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);	
				}
				
				function deactive_tiptip(){
					opts.exit.call(this);
					if (timeout){ clearTimeout(timeout); }
					tipHolder.fadeOut(opts.fadeOut);
				}
			}				
		});
	}
})(jQuery);  	